package com.xdb.sqlparser.ast.statement;

import java.util.ArrayList;
import java.util.List;

import com.xdb.sqlparser.ast.SQLExpr;
import com.xdb.sqlparser.ast.SQLName;
import com.xdb.sqlparser.ast.AbstractSQLObjectImpl;
import com.xdb.sqlparser.ast.AbstractSQLStatementImpl;
import com.xdb.sqlparser.ast.expr.SQLCharExpr;
import com.xdb.sqlparser.ast.expr.SQLLiteralExpr;
import com.xdb.sqlparser.visitor.SQLAstVisitor;

public class SQLCreateViewStatement extends AbstractSQLStatementImpl implements SQLDDLStatement {

	private boolean orReplace = false;
	protected SQLName name;
	protected SQLSelect subQuery;
	protected boolean ifNotExists = false;

	protected final List<Column> columns = new ArrayList<Column>();

	private Level with;

	private SQLLiteralExpr comment;

	public SQLCreateViewStatement() {

	}

	public SQLCreateViewStatement(String dbType) {
		super(dbType);
	}

	public boolean isOrReplace() {
		return orReplace;
	}

	public void setOrReplace(boolean orReplace) {
		this.orReplace = orReplace;
	}

	public SQLName getName() {
		return name;
	}

	public void setName(SQLName name) {
		this.name = name;
	}

	public Level getWith() {
		return with;
	}

	public void setWith(Level with) {
		this.with = with;
	}

	public SQLSelect getSubQuery() {
		return subQuery;
	}

	public void setSubQuery(SQLSelect subQuery) {
		this.subQuery = subQuery;
	}

	public List<Column> getColumns() {
		return columns;
	}

	public boolean isIfNotExists() {
		return ifNotExists;
	}

	public void setIfNotExists(boolean ifNotExists) {
		this.ifNotExists = ifNotExists;
	}

	public SQLLiteralExpr getComment() {
		return comment;
	}

	public void setComment(SQLLiteralExpr comment) {
		if (comment != null) {
			comment.setParent(this);
		}
		this.comment = comment;
	}

	public void output(StringBuffer buf) {
		buf.append("CREATE VIEW ");
		this.name.output(buf);

		if (this.columns.size() > 0) {
			buf.append(" (");
			for (int i = 0, size = this.columns.size(); i < size; ++i) {
				if (i != 0) {
					buf.append(", ");
				}
				this.columns.get(i).output(buf);
			}
			buf.append(")");
		}

		buf.append(" AS ");
		this.subQuery.output(buf);

		if (this.with != null) {
			buf.append(" WITH ");
			buf.append(this.with.name());
		}
	}

	@Override
	protected void accept0(SQLAstVisitor visitor) {
		if (visitor.visit(this)) {
			acceptChild(visitor, this.name);
			acceptChild(visitor, this.columns);
			acceptChild(visitor, this.comment);
			acceptChild(visitor, this.subQuery);
		}
		visitor.endVisit(this);
	}

	public static enum Level {
		CASCADED, LOCAL
	}

	public static class Column extends AbstractSQLObjectImpl {

		private SQLExpr expr;
		private SQLCharExpr comment;

		public SQLExpr getExpr() {
			return expr;
		}

		public void setExpr(SQLExpr expr) {
			if (expr != null) {
				expr.setParent(this);
			}
			this.expr = expr;
		}

		public SQLCharExpr getComment() {
			return comment;
		}

		public void setComment(SQLCharExpr comment) {
			if (comment != null) {
				comment.setParent(this);
			}
			this.comment = comment;
		}

		@Override
		protected void accept0(SQLAstVisitor visitor) {
			if (visitor.visit(this)) {
				acceptChild(visitor, expr);
				acceptChild(visitor, comment);
			}
		}
	}
}
